Add a combo box cell renderer.
authorMatthias Clasen <matthiasc@src.gnome.org>
Fri, 16 Jul 2004 20:27:40 +0000 (20:27 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Fri, 16 Jul 2004 20:27:40 +0000 (20:27 +0000)
13 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/Makefile.am
gtk/gtk.h
gtk/gtkcellrenderercombo.c [new file with mode: 0644]
gtk/gtkcellrenderercombo.h [new file with mode: 0644]
gtk/gtkcombobox.c
gtk/gtkcombobox.h
gtk/gtkcomboboxentry.c
gtk/gtkmarshalers.list
gtk/gtktreeview.c

index b15ca79470874ae3c6243dfc0d2d33d2bb704d98..452243d8f22294b17b6d97a984fe5fc63ae17559 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2004-07-16  Matthias Clasen  <mclasen@redhat.com>
+
+       Add a combo box cell renderer (#139347, Lorenzo Gil Sanchez)
+       
+       * gtk/gtkcellrenderercombo.[hc]: New Files.
+
+       * gtk/gtk.h: 
+       * gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources): 
+       Add the new files.
+
+       * gtk/gtkcombobox.[hc]: Implement GtkCellEditable, add a 
+       :has-frame property for suppressing the frame around 
+       the child and redo the size allocation logic to take 
+       focus width into account.
+
+       * gtk/gtkcomboboxentry.c (gtk_combo_box_entry_init): 
+       Acknowledge the GtkComboBox:has-frame property and make
+       the entry fill its allocation vertically.
+
+       * gtk/gtkmarshalers.list: Add BOOLEAN:STRING.
+               
+       * gtk/gtktreeview.c (gtk_tree_view_remove_widget): Queue
+       a draw here to keep non-widget windows from leaving 
+       shadows behind.
+
 2004-07-16  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcombobox.c (gtk_combo_box_forall): Don't iterate
index b15ca79470874ae3c6243dfc0d2d33d2bb704d98..452243d8f22294b17b6d97a984fe5fc63ae17559 100644 (file)
@@ -1,3 +1,28 @@
+2004-07-16  Matthias Clasen  <mclasen@redhat.com>
+
+       Add a combo box cell renderer (#139347, Lorenzo Gil Sanchez)
+       
+       * gtk/gtkcellrenderercombo.[hc]: New Files.
+
+       * gtk/gtk.h: 
+       * gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources): 
+       Add the new files.
+
+       * gtk/gtkcombobox.[hc]: Implement GtkCellEditable, add a 
+       :has-frame property for suppressing the frame around 
+       the child and redo the size allocation logic to take 
+       focus width into account.
+
+       * gtk/gtkcomboboxentry.c (gtk_combo_box_entry_init): 
+       Acknowledge the GtkComboBox:has-frame property and make
+       the entry fill its allocation vertically.
+
+       * gtk/gtkmarshalers.list: Add BOOLEAN:STRING.
+               
+       * gtk/gtktreeview.c (gtk_tree_view_remove_widget): Queue
+       a draw here to keep non-widget windows from leaving 
+       shadows behind.
+
 2004-07-16  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcombobox.c (gtk_combo_box_forall): Don't iterate
index b15ca79470874ae3c6243dfc0d2d33d2bb704d98..452243d8f22294b17b6d97a984fe5fc63ae17559 100644 (file)
@@ -1,3 +1,28 @@
+2004-07-16  Matthias Clasen  <mclasen@redhat.com>
+
+       Add a combo box cell renderer (#139347, Lorenzo Gil Sanchez)
+       
+       * gtk/gtkcellrenderercombo.[hc]: New Files.
+
+       * gtk/gtk.h: 
+       * gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources): 
+       Add the new files.
+
+       * gtk/gtkcombobox.[hc]: Implement GtkCellEditable, add a 
+       :has-frame property for suppressing the frame around 
+       the child and redo the size allocation logic to take 
+       focus width into account.
+
+       * gtk/gtkcomboboxentry.c (gtk_combo_box_entry_init): 
+       Acknowledge the GtkComboBox:has-frame property and make
+       the entry fill its allocation vertically.
+
+       * gtk/gtkmarshalers.list: Add BOOLEAN:STRING.
+               
+       * gtk/gtktreeview.c (gtk_tree_view_remove_widget): Queue
+       a draw here to keep non-widget windows from leaving 
+       shadows behind.
+
 2004-07-16  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcombobox.c (gtk_combo_box_forall): Don't iterate
index b15ca79470874ae3c6243dfc0d2d33d2bb704d98..452243d8f22294b17b6d97a984fe5fc63ae17559 100644 (file)
@@ -1,3 +1,28 @@
+2004-07-16  Matthias Clasen  <mclasen@redhat.com>
+
+       Add a combo box cell renderer (#139347, Lorenzo Gil Sanchez)
+       
+       * gtk/gtkcellrenderercombo.[hc]: New Files.
+
+       * gtk/gtk.h: 
+       * gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources): 
+       Add the new files.
+
+       * gtk/gtkcombobox.[hc]: Implement GtkCellEditable, add a 
+       :has-frame property for suppressing the frame around 
+       the child and redo the size allocation logic to take 
+       focus width into account.
+
+       * gtk/gtkcomboboxentry.c (gtk_combo_box_entry_init): 
+       Acknowledge the GtkComboBox:has-frame property and make
+       the entry fill its allocation vertically.
+
+       * gtk/gtkmarshalers.list: Add BOOLEAN:STRING.
+               
+       * gtk/gtktreeview.c (gtk_tree_view_remove_widget): Queue
+       a draw here to keep non-widget windows from leaving 
+       shadows behind.
+
 2004-07-16  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcombobox.c (gtk_combo_box_forall): Don't iterate
index b515866175a8346706abd98499269cd6d42cca52..cd490b0b0a2956ee620c6d3da91701bc736c5b45 100644 (file)
@@ -118,6 +118,7 @@ gtk_public_h_sources =          \
        gtkcelleditable.h       \
        gtkcelllayout.h         \
        gtkcellrenderer.h       \
+       gtkcellrenderercombo.h  \
        gtkcellrendererpixbuf.h \
        gtkcellrendererprogress.h \
        gtkcellrenderertext.h   \
@@ -324,6 +325,7 @@ gtk_c_sources =                 \
        gtkcelleditable.c       \
        gtkcelllayout.c         \
        gtkcellrenderer.c       \
+       gtkcellrenderercombo.c  \
        gtkcellrendererpixbuf.c \
        gtkcellrendererprogress.c \
        gtkcellrendererseptext.c\
index f9494dba79eee70be24d728375eb98581ddb85a9..03e30a37b7e532afe95d7d02b526ccd9340c6778 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -48,6 +48,7 @@
 #include <gtk/gtkcalendar.h>
 #include <gtk/gtkcelllayout.h>
 #include <gtk/gtkcellrenderer.h>
+#include <gtk/gtkcellrenderercombo.h>
 #include <gtk/gtkcellrendererpixbuf.h>
 #include <gtk/gtkcellrendererprogress.h>
 #include <gtk/gtkcellrenderertext.h>
diff --git a/gtk/gtkcellrenderercombo.c b/gtk/gtkcellrenderercombo.c
new file mode 100644 (file)
index 0000000..e03a487
--- /dev/null
@@ -0,0 +1,390 @@
+/* GtkCellRendererCombo
+ * Copyright (C) 2004 Lorenzo Gil Sanchez
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "gtkintl.h"
+#include "gtkbin.h"
+#include "gtkentry.h"
+#include "gtkcelllayout.h"
+#include "gtkcellrenderercombo.h"
+#include "gtkcellrenderertext.h"
+#include "gtkcombobox.h"
+#include "gtkcomboboxentry.h"
+
+static void gtk_cell_renderer_combo_class_init (GtkCellRendererComboClass *klass);
+static void gtk_cell_renderer_combo_init       (GtkCellRendererCombo      *self);
+static void gtk_cell_renderer_combo_get_property (GObject      *object,
+                                                 guint         prop_id,
+                                                 GValue       *value,
+                                                 GParamSpec   *pspec);
+
+static void gtk_cell_renderer_combo_set_property (GObject      *object,
+                                                 guint         prop_id,
+                                                 const GValue *value,
+                                                 GParamSpec   *pspec);
+
+static GtkCellEditable *gtk_cell_renderer_combo_start_editing (GtkCellRenderer     *cell,
+                                                              GdkEvent            *event,
+                                                              GtkWidget           *widget,
+                                                              const gchar         *path,
+                                                              GdkRectangle        *background_area,
+                                                              GdkRectangle        *cell_area,
+                                                              GtkCellRendererState flags);
+
+enum {
+  PROP_0,
+  PROP_MODEL,
+  PROP_TEXT_COLUMN,
+  PROP_HAS_ENTRY
+};
+
+static GObjectClass *parent_class = NULL;
+
+#define GTK_CELL_RENDERER_COMBO_PATH "gtk-cell-renderer-combo-path"
+
+GType
+gtk_cell_renderer_combo_get_type (void)
+{
+  static GType gtk_cell_renderer_combo_type = 0;
+
+  if (!gtk_cell_renderer_combo_type)
+    {
+      static const GTypeInfo gtk_cell_renderer_combo_info = 
+       {
+         sizeof (GtkCellRendererComboClass),
+         (GBaseInitFunc)     NULL,
+         (GBaseFinalizeFunc) NULL,
+         (GClassInitFunc)    gtk_cell_renderer_combo_class_init,
+         NULL,
+         NULL,
+         sizeof (GtkCellRendererCombo),
+         0,
+         (GInstanceInitFunc) gtk_cell_renderer_combo_init
+       };
+      gtk_cell_renderer_combo_type =
+       g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT,
+                               "GtkCellRendererCombo",
+                               &gtk_cell_renderer_combo_info,
+                               0);
+    }
+  return gtk_cell_renderer_combo_type;
+}
+
+static void
+gtk_cell_renderer_combo_class_init (GtkCellRendererComboClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->get_property = gtk_cell_renderer_combo_get_property;
+  object_class->set_property = gtk_cell_renderer_combo_set_property;
+
+  cell_class->start_editing = gtk_cell_renderer_combo_start_editing;
+
+  /**
+   * GtkCellRendererCombo:model:
+   *
+   * The :model property holds a tree model containing the possible
+   * values for the combo box. Use the :text_column property to specify
+   * the column holding the values.
+   * 
+   * Since: 2.6
+   */
+  g_object_class_install_property (object_class,
+                                  PROP_MODEL,
+                                  g_param_spec_object ("model",
+                                                       P_("Model"),
+                                                       P_("The model containing the possible values for the combo box"),
+                                                       GTK_TYPE_TREE_MODEL,
+                                                       G_PARAM_READWRITE));
+
+  /**
+   * GtkCellRendererCombo:text_column:
+   *
+   * The :text_column property specifies the model column which
+   * holds the possible values for the combo box. Note that this
+   * refers to the model specified in the :model property, 
+   * <emphasis>not</emphasis> the model backing the tree view to 
+   * which this cell renderer is attached.
+   * 
+   * Since: 2.6
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_TEXT_COLUMN,
+                                   g_param_spec_int ("text_column",
+                                                     P_("Text Column"),
+                                                     P_("A column in the data source model to get the strings from"),
+                                                     -1,
+                                                     G_MAXINT,
+                                                     -1,
+                                                     G_PARAM_READWRITE));
+
+  /** 
+   * GtkCellRendererCombo:has_entry:
+   *
+   * If the :has_entry property is %TRUe, the cell renderer will 
+   * include an entry and allow to enter values other than the ones 
+   * in the popup list. 
+   *
+   * Since: 2.6
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_HAS_ENTRY,
+                                   g_param_spec_boolean ("has_entry",
+                                                        P_("Has Entry"),
+                                                        P_("If %FALSE, don't allow to enter strings other than the chosen ones"),
+                                                        TRUE,
+                                                        G_PARAM_READWRITE));
+
+}
+
+static void
+gtk_cell_renderer_combo_init (GtkCellRendererCombo *self)
+{
+  self->model = NULL;
+  self->text_column = -1;
+  self->focus_out_id = 0;
+}
+
+/**
+ * gtk_cell_renderer_combo_new: 
+ * 
+ * Creates a new #GtkCellRendererCombo 
+ * Adjust how text is drawn using object properties. 
+ * Object properties can be set globally (with g_object_set()). 
+ * Also, with #GtkTreeViewColumn, you can bind a property to a value 
+ * in a #GtkTreeModel. For example, you can bind the "text" property 
+ * on the cell renderer to a string value in the model, thus rendering 
+ * a different string in each row of the #GtkTreeView.
+ * 
+ * Returns: the new cell renderer
+ *
+ * Since: 2.6
+ */
+GtkCellRenderer *
+gtk_cell_renderer_combo_new (void)
+{
+  return g_object_new (GTK_TYPE_CELL_RENDERER_COMBO, NULL); 
+}
+
+static void
+gtk_cell_renderer_combo_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  GtkCellRendererCombo *cell;
+  g_return_if_fail (GTK_IS_CELL_RENDERER_COMBO (object));
+
+  cell = GTK_CELL_RENDERER_COMBO (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODEL:
+      g_value_set_object (value, cell->model);
+      break; 
+    case PROP_TEXT_COLUMN:
+      g_value_set_int (value, cell->text_column);
+      break;
+    case PROP_HAS_ENTRY:
+      g_value_set_boolean (value, cell->has_entry);
+      break;
+   default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtk_cell_renderer_combo_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  GtkCellRendererCombo *cell;
+  
+  g_return_if_fail (GTK_IS_CELL_RENDERER_COMBO (object));
+
+  cell = GTK_CELL_RENDERER_COMBO (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODEL:
+      cell->model = g_value_get_object (value);
+      break;
+    case PROP_TEXT_COLUMN:
+      cell->text_column = g_value_get_int (value);
+      break;
+    case PROP_HAS_ENTRY:
+      cell->has_entry = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtk_cell_renderer_combo_editing_done (GtkCellEditable *combo,
+                                     gpointer         data)
+{
+  const gchar *path;
+  gchar *new_text = NULL;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GtkCellRendererCombo *cell;
+  GtkEntry *entry;
+
+  cell = GTK_CELL_RENDERER_COMBO (data);
+
+  if (cell->focus_out_id > 0)
+    {
+      g_signal_handler_disconnect (combo, cell->focus_out_id);
+      cell->focus_out_id = 0;
+    }
+
+  if (_gtk_combo_box_editing_canceled (GTK_COMBO_BOX (combo)))
+    {
+      gtk_cell_renderer_editing_canceled (GTK_CELL_RENDERER (data));
+      return;
+    }
+
+  if (GTK_IS_COMBO_BOX_ENTRY (combo))
+    {
+      entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo)));
+      new_text = g_strdup (gtk_entry_get_text (entry));
+    }
+  else 
+    {
+      model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+      if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
+       gtk_tree_model_get (model, &iter, cell->text_column, &new_text, -1);
+    }
+
+  path = g_object_get_data (G_OBJECT (combo), GTK_CELL_RENDERER_COMBO_PATH);
+  g_signal_emit_by_name (cell, "edited", path, new_text);
+
+  g_free (new_text);
+}
+
+static gboolean
+gtk_cell_renderer_combo_focus_out_event (GtkWidget *widget,
+                                        GdkEvent  *event,
+                                        gpointer   data)
+{
+  
+  gtk_cell_renderer_combo_editing_done (GTK_CELL_EDITABLE (widget), data);
+
+  return FALSE;
+}
+
+typedef struct 
+{
+  GtkCellRendererCombo *cell;
+  gboolean found;
+  GtkTreeIter iter;
+} SearchData;
+
+static gboolean 
+find_text (GtkTreeModel *model, 
+          GtkTreePath  *path, 
+          GtkTreeIter  *iter, 
+          gpointer      data)
+{
+  SearchData *search_data = (SearchData *)data;
+  gchar *text;
+  
+  gtk_tree_model_get (model, iter, search_data->cell->text_column, &text, -1);
+  if (text && GTK_CELL_RENDERER_TEXT (search_data->cell)->text &&
+      strcmp (text, GTK_CELL_RENDERER_TEXT (search_data->cell)->text) == 0)
+    {
+      search_data->iter = *iter;
+      search_data->found = TRUE;
+    }
+  
+  return search_data->found;
+}
+
+static GtkCellEditable *
+gtk_cell_renderer_combo_start_editing (GtkCellRenderer     *cell,
+                                      GdkEvent            *event,
+                                      GtkWidget           *widget,
+                                      const gchar         *path,
+                                      GdkRectangle        *background_area,
+                                      GdkRectangle        *cell_area,
+                                      GtkCellRendererState flags)
+{
+  GtkCellRendererCombo *cell_combo;
+  GtkCellRendererText *cell_text;
+  GtkWidget *combo;
+  SearchData search_data;
+
+  cell_text = GTK_CELL_RENDERER_TEXT (cell);
+  if (cell_text->editable == FALSE)
+    return NULL;
+
+  cell_combo = GTK_CELL_RENDERER_COMBO (cell);
+  if (cell_combo->model == NULL || cell_combo->text_column < 0)
+    return NULL;
+
+  if (cell_combo->has_entry) 
+    {
+      combo = gtk_combo_box_entry_new_with_model (cell_combo->model, cell_combo->text_column);
+
+      if (cell_text->text)
+       gtk_entry_set_text (GTK_ENTRY (GTK_BIN (combo)->child), 
+                           cell_text->text);
+    }
+  else
+    {
+      cell = gtk_cell_renderer_text_new ();
+      combo = gtk_combo_box_new_with_model (cell_combo->model);
+      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
+      gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), 
+                                     cell, "text", cell_combo->text_column, 
+                                     NULL);
+
+      /* determine the current value */
+      search_data.cell = cell_combo;
+      search_data.found = FALSE;
+      gtk_tree_model_foreach (cell_combo->model, find_text, &search_data);
+      if (search_data.found)
+       gtk_combo_box_set_active_iter (combo, &(search_data.iter));
+    }
+
+  g_object_set (combo, "has_frame", FALSE, NULL);
+  g_object_set_data_full (G_OBJECT (combo),
+                         GTK_CELL_RENDERER_COMBO_PATH,
+                         g_strdup (path), g_free);
+
+  gtk_widget_show (combo);
+
+  g_signal_connect (GTK_CELL_EDITABLE (combo), "editing_done",
+                   G_CALLBACK (gtk_cell_renderer_combo_editing_done),
+                   cell_combo);
+  cell_combo->focus_out_id = 
+    g_signal_connect (combo, "focus_out_event",
+                     G_CALLBACK (gtk_cell_renderer_combo_focus_out_event),
+                     cell_combo);
+
+  return GTK_CELL_EDITABLE (combo);
+}
diff --git a/gtk/gtkcellrenderercombo.h b/gtk/gtkcellrenderercombo.h
new file mode 100644 (file)
index 0000000..8168543
--- /dev/null
@@ -0,0 +1,61 @@
+/* GtkCellRendererCombo
+ * Copyright (C) 2004 Lorenzo Gil Sanchez
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef GTK_CELL_RENDERER_COMBO_H
+#define GTK_CELL_RENDERER_COMBO_H
+
+#include <gtk/gtktreemodel.h>
+#include <gtk/gtkcellrenderertext.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CELL_RENDERER_COMBO           (gtk_cell_renderer_combo_get_type ())
+#define GTK_CELL_RENDERER_COMBO(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_RENDERER_COMBO, GtkCellRendererCombo))
+#define GTK_CELL_RENDERER_COMBO_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_COMBO, GtkCellRendererComboClass))
+#define GTK_IS_CELL_RENDERER_COMBO(obj)                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_RENDERER_COMBO))
+#define GTK_IS_CELL_RENDERER_COMBO_CLASS(klass)        (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CELL_RENDERER_COMBO))
+#define GTK_CELL_RENDERER_COMBO_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CELL_RENDERER_COMBO, GtkCellRendererTextClass))
+                                                
+typedef struct _GtkCellRendererCombo GtkCellRendererCombo;
+typedef struct _GtkCellRendererComboClass GtkCellRendererComboClass;
+
+struct _GtkCellRendererCombo
+{
+  GtkCellRendererText parent;
+
+  GtkTreeModel *model;
+  gint          text_column;
+  gboolean      has_entry;
+  
+  /*< private >*/
+  guint         focus_out_id;
+};
+
+struct _GtkCellRendererComboClass
+{
+  GtkCellRendererTextClass parent;
+};
+
+GType            gtk_cell_renderer_combo_get_type (void);
+GtkCellRenderer *gtk_cell_renderer_combo_new      (void);
+
+G_END_DECLS
+
+#endif
index a00b54a0bc7a0cdba4f053561a41b77dffd913b9..8471f74f3d7cb5e20733aa92bce2e98c45d6dc8e 100644 (file)
@@ -99,6 +99,7 @@ struct _GtkComboBoxPrivate
   guint deleted_id;
   guint reordered_id;
   guint changed_id;
+  guint popup_idle_id;
 
   gint width;
   GSList *cells;
@@ -106,6 +107,9 @@ struct _GtkComboBoxPrivate
   guint popup_in_progress : 1;
   guint destroying : 1;
   guint add_tearoffs : 1;
+  guint has_frame : 1;
+  guint is_cell_renderer : 1;
+  guint editing_canceled : 1;
 };
 
 /* While debugging this evil code, I have learned that
@@ -175,7 +179,8 @@ enum {
   PROP_COLUMN_SPAN_COLUMN,
   PROP_ROW_SEPARATOR_COLUMN,
   PROP_ACTIVE,
-  PROP_ADD_TEAROFFS
+  PROP_ADD_TEAROFFS,
+  PROP_HAS_FRAME
 };
 
 static GtkBinClass *parent_class = NULL;
@@ -187,6 +192,7 @@ static guint combo_box_signals[LAST_SIGNAL] = {0,};
 /* common */
 static void     gtk_combo_box_class_init           (GtkComboBoxClass *klass);
 static void     gtk_combo_box_cell_layout_init     (GtkCellLayoutIface *iface);
+static void     gtk_combo_box_cell_editable_init   (GtkCellEditableIface *iface);
 static void     gtk_combo_box_init                 (GtkComboBox      *combo_box);
 static void     gtk_combo_box_finalize             (GObject          *object);
 static void     gtk_combo_box_destroy              (GtkObject        *object);
@@ -261,6 +267,8 @@ static gboolean gtk_combo_box_key_press            (GtkWidget        *widget,
                                                    GdkEventKey      *event,
                                                    gpointer          data);
 
+static void     gtk_combo_box_check_appearance     (GtkComboBox      *combo_box);
+
 /* listening to the model */
 static void     gtk_combo_box_model_row_inserted   (GtkTreeModel     *model,
                                                    GtkTreePath      *path,
@@ -375,6 +383,11 @@ static gboolean gtk_combo_box_mnemonic_activate              (GtkWidget    *widg
 static void     cell_view_sync_cells (GtkComboBox *combo_box,
                                       GtkCellView *cell_view);
 
+/* GtkCellEditable method implementations */
+static void gtk_combo_box_start_editing (GtkCellEditable *cell_editable,
+                                        GdkEvent        *event);
+
+
 GType
 gtk_combo_box_get_type (void)
 {
@@ -402,6 +415,13 @@ gtk_combo_box_get_type (void)
           NULL
         };
 
+      static const GInterfaceInfo cell_editable_info =
+       {
+         (GInterfaceInitFunc) gtk_combo_box_cell_editable_init,
+         NULL,
+         NULL
+       };
+
       combo_box_type = g_type_register_static (GTK_TYPE_BIN,
                                                "GtkComboBox",
                                                &combo_box_info,
@@ -410,6 +430,13 @@ gtk_combo_box_get_type (void)
       g_type_add_interface_static (combo_box_type,
                                    GTK_TYPE_CELL_LAYOUT,
                                    &cell_layout_info);
+
+
+      g_type_add_interface_static (combo_box_type,
+                                  GTK_TYPE_CELL_EDITABLE,
+                                  &cell_editable_info);
+      
+
     }
 
   return combo_box_type;
@@ -534,14 +561,30 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
                                    PROP_ADD_TEAROFFS,
                                   g_param_spec_boolean ("add-tearoffs",
                                                         P_("Add tearoffs to menus"),
-                                                        P_("Whether combobox dropdowns should have a tearoff menu item"),
+                                                        P_("Whether dropdowns should have a tearoff menu item"),
                                                         FALSE,
                                                         G_PARAM_READWRITE));
   
+  /**
+   * GtkComboBox:has-frame:
+   *
+   * The :has-frame property controls whether a frame
+   * is drawn around the entry.
+   *
+   * Since: 2.6
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_HAS_FRAME,
+                                  g_param_spec_boolean ("has-frame",
+                                                        P_("Has Frame"),
+                                                        P_("Whether the combo box draws a frame around the child"),
+                                                        TRUE,
+                                                        G_PARAM_READWRITE));
+  
   gtk_widget_class_install_style_property (widget_class,
                                            g_param_spec_boolean ("appears-as-list",
                                                                  P_("Appears as list"),
-                                                                 P_("Whether combobox dropdowns should look like lists rather than menus"),
+                                                                 P_("Whether dropdowns should look like lists rather than menus"),
                                                                  FALSE,
                                                                  G_PARAM_READABLE));
 
@@ -560,6 +603,12 @@ gtk_combo_box_cell_layout_init (GtkCellLayoutIface *iface)
   iface->reorder = gtk_combo_box_cell_layout_reorder;
 }
 
+static void
+gtk_combo_box_cell_editable_init (GtkCellEditableIface *iface)
+{
+  iface->start_editing = gtk_combo_box_start_editing;
+}
+
 static void
 gtk_combo_box_init (GtkComboBox *combo_box)
 {
@@ -577,6 +626,11 @@ gtk_combo_box_init (GtkComboBox *combo_box)
   combo_box->priv->col_column = -1;
   combo_box->priv->row_column = -1;
   combo_box->priv->separator_column = -1;
+
+  combo_box->priv->add_tearoffs = FALSE;
+  combo_box->priv->has_frame = TRUE;
+  combo_box->priv->is_cell_renderer = FALSE;
+  combo_box->priv->editing_canceled = FALSE;
 }
 
 static void
@@ -617,6 +671,10 @@ gtk_combo_box_set_property (GObject      *object,
         gtk_combo_box_set_add_tearoffs (combo_box, g_value_get_boolean (value));
         break;
 
+      case PROP_HAS_FRAME:
+        combo_box->priv->has_frame = g_value_get_boolean (value);
+        break;
+
       default:
         break;
     }
@@ -660,6 +718,10 @@ gtk_combo_box_get_property (GObject    *object,
         g_value_set_boolean (value, gtk_combo_box_get_add_tearoffs (combo_box));
         break;
 
+      case PROP_HAS_FRAME:
+        g_value_set_boolean (value, combo_box->priv->has_frame);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -781,6 +843,7 @@ gtk_combo_box_add (GtkContainer *container,
         {
           gtk_widget_unparent (combo_box->priv->cell_view_frame);
           combo_box->priv->cell_view_frame = NULL;
+          combo_box->priv->box = NULL;
         }
     }
 }
@@ -1138,7 +1201,7 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
 
   gdk_window_get_origin (sample->window, x, y);
 
-  if (combo_box->priv->cell_view_frame)
+  if (combo_box->priv->cell_view_frame && combo_box->priv->has_frame)
     {
        *x -= GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
             GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness;
@@ -1501,6 +1564,7 @@ gtk_combo_box_size_request (GtkWidget      *widget,
                             GtkRequisition *requisition)
 {
   gint width, height;
+  gint focus_width, focus_pad;
   GtkRequisition bin_req;
 
   GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
@@ -1510,6 +1574,11 @@ gtk_combo_box_size_request (GtkWidget      *widget,
   gtk_combo_box_remeasure (combo_box);
   bin_req.width = MAX (bin_req.width, combo_box->priv->width);
 
+  gtk_widget_style_get (GTK_WIDGET (widget),
+                       "focus-line-width", &focus_width,
+                       "focus-padding", &focus_pad,
+                       NULL);
+
   if (!combo_box->priv->tree_view)
     {
       /* menu mode */
@@ -1520,7 +1589,7 @@ gtk_combo_box_size_request (GtkWidget      *widget,
           gint border_width, xthickness, ythickness;
 
           gtk_widget_size_request (combo_box->priv->button, &button_req);
-          border_width = GTK_CONTAINER (combo_box->priv->button)->border_width;
+         border_width = GTK_CONTAINER (combo_box)->border_width;
           xthickness = combo_box->priv->button->style->xthickness;
           ythickness = combo_box->priv->button->style->ythickness;
 
@@ -1534,8 +1603,8 @@ gtk_combo_box_size_request (GtkWidget      *widget,
 
           width = bin_req.width + sep_req.width + arrow_req.width;
 
-          height += border_width + 1 + ythickness * 2 + 4;
-          width += border_width + 1 + xthickness * 2 + 4;
+          height += 2*(border_width + ythickness + focus_width + focus_pad);
+          width  += 2*(border_width + xthickness + focus_width + focus_pad);
 
           requisition->width = width;
           requisition->height = height;
@@ -1561,12 +1630,15 @@ gtk_combo_box_size_request (GtkWidget      *widget,
       if (combo_box->priv->cell_view_frame)
         {
          gtk_widget_size_request (combo_box->priv->cell_view_frame, &frame_req);
-          requisition->width += 2 *
-            (GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
-             GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness);
-          requisition->height += 2 *
-            (GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
-             GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness);
+         if (combo_box->priv->has_frame)
+           {
+             requisition->width += 2 *
+               (GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
+                GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness);
+             requisition->height += 2 *
+               (GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
+                GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness);
+           }
         }
 
       /* the button */
@@ -1582,12 +1654,18 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
                              GtkAllocation *allocation)
 {
   GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
+  gint focus_width, focus_pad;
   GtkAllocation child;
   GtkRequisition req;
   gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
 
   widget->allocation = *allocation;
 
+  gtk_widget_style_get (GTK_WIDGET (widget),
+                       "focus-line-width", &focus_width,
+                       "focus-padding", &focus_pad,
+                       NULL);
+
   if (!combo_box->priv->tree_view)
     {
       if (combo_box->priv->cell_view)
@@ -1603,15 +1681,23 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
           xthickness = combo_box->priv->button->style->xthickness;
           ythickness = combo_box->priv->button->style->ythickness;
 
-          child.x = allocation->x + border_width + 1 + xthickness + 2;
-          child.y = allocation->y + border_width + 1 + ythickness + 2;
+          child.x = allocation->x;
+          child.y = allocation->y;
+         width = allocation->width;
+         child.height = allocation->height;
+
+         if (!combo_box->priv->is_cell_renderer)
+           {
+             child.x += border_width + xthickness + focus_width + focus_pad;
+             child.y += border_width + ythickness + focus_width + focus_pad;
+             width -= 2 * (child.x - allocation->x);
+             child.height -= 2 * (child.y - allocation->y);
+           }
 
-          width = allocation->width - (border_width + 1 + xthickness * 2 + 4);
 
           /* handle the children */
           gtk_widget_size_request (combo_box->priv->arrow, &req);
           child.width = req.width;
-          child.height = allocation->height - 2 * (child.y - allocation->y);
           if (!is_rtl)
             child.x += width - req.width;
           gtk_widget_size_allocate (combo_box->priv->arrow, &child);
@@ -1627,12 +1713,14 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
             {
               child.x += req.width;
               child.width = allocation->x + allocation->width 
-                - (border_width + 1 + xthickness + 2) - child.x;
+                - (border_width + xthickness + focus_width + focus_pad) 
+               - child.x;
             }
           else 
             {
               child.width = child.x;
-              child.x = allocation->x + border_width + 1 + xthickness + 2;
+              child.x = allocation->x 
+               + border_width + xthickness + focus_width + focus_pad;
               child.width -= child.x;
             }
 
@@ -1688,20 +1776,23 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
           gtk_widget_size_allocate (combo_box->priv->cell_view_frame, &child);
 
           /* the sample */
-          child.x +=
-            GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
-            GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness;
-          child.y +=
-            GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
-            GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness;
-          child.width -= 2 * (
-            GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
-            GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness);
-          child.height -= 2 * (
-            GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
-            GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness);
+         if (combo_box->priv->has_frame)
+           {
+             child.x +=
+               GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
+               GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness;
+             child.y +=
+               GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
+               GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness;
+             child.width -= 2 * (
+                                 GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
+                                 GTK_WIDGET (combo_box->priv->cell_view_frame)->style->xthickness);
+             child.height -= 2 * (
+                                  GTK_CONTAINER (combo_box->priv->cell_view_frame)->border_width +
+                                  GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness);
+           }
         }
-
+      
       gtk_widget_size_allocate (GTK_BIN (combo_box)->child, &child);
     }
 }
@@ -1768,7 +1859,7 @@ gtk_combo_box_expose_event (GtkWidget      *widget,
   if (!combo_box->priv->tree_view)
     {
       gtk_container_propagate_expose (GTK_CONTAINER (widget),
-                                      combo_box->priv->button, event);
+                                     combo_box->priv->button, event);
     }
   else
     {
@@ -1869,7 +1960,8 @@ gtk_combo_box_menu_setup (GtkComboBox *combo_box,
       combo_box->priv->button = gtk_toggle_button_new ();
       g_signal_connect (combo_box->priv->button, "toggled",
                         G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
-      g_signal_connect_after (combo_box->priv->button, "key_press_event",
+      g_signal_connect_after (combo_box->priv->button, 
+                             "key_press_event",
                              G_CALLBACK (gtk_combo_box_key_press), combo_box);
       gtk_widget_set_parent (combo_box->priv->button,
                              GTK_BIN (combo_box)->child->parent);
@@ -2226,6 +2318,8 @@ gtk_combo_box_menu_item_activate (GtkWidget *item,
   index = g_list_index (children, item);
 
   gtk_combo_box_set_active (combo_box, index);
+
+  combo_box->priv->editing_canceled = FALSE;
 }
 
 static void
@@ -2448,12 +2542,6 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
 
   if (combo_box->priv->cell_view)
     {
-      combo_box->priv->cell_view_frame = gtk_frame_new (NULL);
-      gtk_widget_set_parent (combo_box->priv->cell_view_frame,
-                             GTK_BIN (combo_box)->child->parent);
-      gtk_frame_set_shadow_type (GTK_FRAME (combo_box->priv->cell_view_frame),
-                                 GTK_SHADOW_IN);
-
       gtk_cell_view_set_background_color (GTK_CELL_VIEW (combo_box->priv->cell_view), 
                                          &GTK_WIDGET (combo_box)->style->base[GTK_WIDGET_STATE (combo_box)]);
 
@@ -2461,9 +2549,23 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
       gtk_event_box_set_visible_window (GTK_EVENT_BOX (combo_box->priv->box), 
                                        FALSE);
 
+      if (combo_box->priv->has_frame)
+       {
+         combo_box->priv->cell_view_frame = gtk_frame_new (NULL);
+         gtk_frame_set_shadow_type (GTK_FRAME (combo_box->priv->cell_view_frame),
+                                    GTK_SHADOW_IN);
+       }
+      else 
+       {
+         combo_box->priv->cell_view_frame = gtk_event_box_new ();
+         gtk_event_box_set_visible_window (GTK_EVENT_BOX (combo_box->priv->cell_view_frame), 
+                                           FALSE);
+       }
+      
+      gtk_widget_set_parent (combo_box->priv->cell_view_frame,
+                            GTK_BIN (combo_box)->child->parent);
       gtk_container_add (GTK_CONTAINER (combo_box->priv->cell_view_frame),
                         combo_box->priv->box);
-
       gtk_widget_show_all (combo_box->priv->cell_view_frame);
 
       g_signal_connect (combo_box->priv->box, "button_press_event",
@@ -3879,10 +3981,19 @@ gtk_combo_box_destroy (GtkObject *object)
 {
   GtkComboBox *combo_box = GTK_COMBO_BOX (object);
 
+  if (combo_box->priv->popup_idle_id > 0)
+    {
+      g_source_remove (combo_box->priv->popup_idle_id);
+      combo_box->priv->popup_idle_id = 0;
+    }
+
   gtk_combo_box_popdown (combo_box);
+
   combo_box->priv->destroying = 1;
+
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
   combo_box->priv->cell_view = NULL;
+
   combo_box->priv->destroying = 0;
 }
 
@@ -3929,7 +4040,120 @@ gtk_combo_box_finalize (GObject *object)
    G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gboolean
+gtk_cell_editable_key_press (GtkWidget   *widget,
+                            GdkEventKey *event,
+                            gpointer     data)
+{
+  GtkComboBox *combo_box = GTK_COMBO_BOX (data);
+
+  if (event->keyval == GDK_Escape)
+    {
+      combo_box->priv->editing_canceled = TRUE;
 
+      gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (combo_box));
+      gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (combo_box));
+      
+      return TRUE;
+    }
+  else if (event->keyval == GDK_Return)
+    {
+      gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (combo_box));
+      if (GTK_IS_CELL_EDITABLE (combo_box))
+       gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (combo_box));
+      
+      return TRUE;
+    }
+  else if (event->keyval == GDK_space)
+    {
+      /* ignore */
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+popdown_idle (gpointer   data)
+{
+  GtkComboBox *combo_box = GTK_COMBO_BOX (data);
+  
+  gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (combo_box));
+  gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (combo_box));
+
+  g_object_unref (combo_box);
+
+  return FALSE;
+}
+
+static void
+popdown_handler (GtkWidget *widget,
+                gpointer   data)
+{
+  g_idle_add (popdown_idle, g_object_ref (data));
+}
+
+static gboolean
+popup_idle (gpointer data)
+{
+  GtkComboBox *combo_box = GTK_COMBO_BOX (data);
+
+  if (GTK_IS_MENU (combo_box->priv->popup_widget) &&
+      combo_box->priv->cell_view)
+    g_signal_connect_object (combo_box->priv->popup_widget,
+                            "unmap", G_CALLBACK (popdown_handler),
+                            combo_box, 0);
+  
+  /* we unset this if a menu item is activated */
+  combo_box->priv->editing_canceled = TRUE;
+  gtk_combo_box_popup (combo_box);
+  
+  return FALSE;
+}
+
+static void
+gtk_combo_box_start_editing (GtkCellEditable *cell_editable,
+                            GdkEvent        *event)
+{
+  GtkComboBox *combo_box = GTK_COMBO_BOX (cell_editable);
+
+  combo_box->priv->is_cell_renderer = TRUE;
+
+  if (combo_box->priv->cell_view)
+    {
+      g_signal_connect (combo_box->priv->button, "key_press_event",
+                       G_CALLBACK (gtk_cell_editable_key_press), 
+                       cell_editable);  
+
+      gtk_widget_grab_focus (combo_box->priv->button);
+    }
+  else
+    {
+      g_signal_connect (GTK_BIN (combo_box)->child, "key_press_event",
+                       G_CALLBACK (gtk_cell_editable_key_press), 
+                       cell_editable);  
+
+      gtk_widget_grab_focus (GTK_WIDGET (GTK_BIN (combo_box)->child));
+      GTK_WIDGET_UNSET_FLAGS (combo_box->priv->button, GTK_CAN_FOCUS);
+    }
+
+  /* we do the immediate popup only for the optionmenu-like 
+   * appearance 
+   */  
+  if (combo_box->priv->is_cell_renderer && 
+      combo_box->priv->cell_view && !combo_box->priv->tree_view)
+    combo_box->priv->popup_idle_id = g_idle_add (popup_idle, combo_box);
+}
+
+
+/**
+ * gtk_combo_box_get_add_tearoffs:
+ * @combo_box: a #GtkComboBox
+ * 
+ * Gets the current value of the :add-tearoffs property.
+ * 
+ * Return value: the current value of the :add-tearoffs property.
+ **/
 gboolean
 gtk_combo_box_get_add_tearoffs (GtkComboBox *combo_box)
 {
@@ -3938,6 +4162,16 @@ gtk_combo_box_get_add_tearoffs (GtkComboBox *combo_box)
   return combo_box->priv->add_tearoffs;
 }
 
+/**
+ * gtk_combo_box_set_add_tearoffs:
+ * @combo_box: a #GtkComboBox 
+ * @add_tearoffs: %TRUE to add tearoff menu items
+ *  
+ * Sets whether the popup menu should have a tearoff 
+ * menu item.
+ *
+ * Since: 2.6
+ **/
 void
 gtk_combo_box_set_add_tearoffs (GtkComboBox *combo_box,
                                gboolean     add_tearoffs)
@@ -3982,7 +4216,7 @@ gtk_combo_box_set_row_separator_column (GtkComboBox *combo_box,
     {
       combo_box->priv->separator_column = column;
 
-      gtk_widget_queue_draw (combo_box);
+      gtk_widget_queue_draw (GTK_WIDGET (combo_box));
 
       g_object_notify (G_OBJECT (combo_box), "row_separator_column");
     }
@@ -4005,3 +4239,11 @@ gtk_combo_box_get_row_separator_column (GtkComboBox *combo_box)
 
   return combo_box->priv->separator_column;
 }
+
+gboolean
+_gtk_combo_box_editing_canceled (GtkComboBox *combo_box)
+{
+  g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), TRUE);
+
+  return combo_box->priv->editing_canceled;
+}
index 4d6b3e460f3ffcce5b4066cf980cf4535ebc9ccd..71e82fbba9ccaf2eea369992497684b2e14ace15 100644 (file)
@@ -115,6 +115,9 @@ gchar        *gtk_combo_box_get_active_text  (GtkComboBox     *combo_box);
 void          gtk_combo_box_popup            (GtkComboBox     *combo_box);
 void          gtk_combo_box_popdown          (GtkComboBox     *combo_box);
 
+/* private */
+gboolean     _gtk_combo_box_editing_canceled (GtkComboBox     *combo_box);
+
 G_END_DECLS
 
 #endif /* __GTK_COMBO_BOX_H__ */
index 72f2e7d948ab2571319f2a669a72f984a7031d36..18927bdbdef8360087659593bba44770139a89de 100644 (file)
@@ -54,6 +54,9 @@ static void gtk_combo_box_entry_contents_changed (GtkEntry              *entry,
                                                   gpointer               user_data);
 static gboolean gtk_combo_box_entry_mnemonic_activate (GtkWidget        *entry,
                                                       gboolean          group_cycling);
+static void has_frame_changed                    (GtkComboBoxEntry      *entry_box,
+                                                 GParamSpec            *pspec,
+                                                 gpointer               data);
 
 enum
 {
@@ -125,6 +128,9 @@ gtk_combo_box_entry_init (GtkComboBoxEntry *entry_box)
   entry_box->priv->text_column = -1;
 
   entry_box->priv->entry = gtk_entry_new ();
+  /* this flag is a hack to tell the entry to fill its allocation.
+   */
+  GTK_ENTRY (entry_box->priv->entry)->is_cell_renderer = TRUE;
   gtk_container_add (GTK_CONTAINER (entry_box), entry_box->priv->entry);
   gtk_widget_show (entry_box->priv->entry);
 
@@ -139,6 +145,8 @@ gtk_combo_box_entry_init (GtkComboBoxEntry *entry_box)
                     entry_box);
   g_signal_connect (entry_box, "changed",
                     G_CALLBACK (gtk_combo_box_entry_active_changed), NULL);
+  has_frame_changed (entry_box, NULL, NULL);
+  g_signal_connect (entry_box, "notify::has-frame", G_CALLBACK (has_frame_changed), NULL);
 }
 
 static void
@@ -217,6 +225,18 @@ gtk_combo_box_entry_active_changed (GtkComboBox *combo_box,
                                      combo_box);
 }
 
+static void 
+has_frame_changed (GtkComboBoxEntry *entry_box,
+                  GParamSpec       *pspec,
+                  gpointer          data)
+{
+  gboolean has_frame;
+  
+  g_object_get (entry_box, "has_frame", &has_frame, NULL);
+
+  gtk_entry_set_has_frame (GTK_ENTRY (entry_box->priv->entry), has_frame);
+}
+
 static void
 gtk_combo_box_entry_contents_changed (GtkEntry *entry,
                                       gpointer  user_data)
index fd65235793771e77bc3cc5a2e000f2823c5ac011..eef9ecc66e8de18ad4f37dc1b6a7a42da982d7b4 100644 (file)
@@ -38,6 +38,7 @@ BOOLEAN:VOID
 BOOLEAN:BOOLEAN
 BOOLEAN:NONE
 BOOLEAN:BOOLEAN,BOOLEAN,BOOLEAN
+BOOLEAN:STRING
 ENUM:ENUM
 INT:POINTER
 NONE:BOOLEAN
index 212384f82ce1d44fdeeecd91e4ad0237b77e5beb..89ba3a603ead304f279182876a4d7658eb1d48d3 100644 (file)
@@ -6784,7 +6784,7 @@ gtk_tree_view_put (GtkTreeView *tree_view,
                   gint         height)
 {
   GtkTreeViewChild *child;
-
+  
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (GTK_IS_WIDGET (child_widget));
 
@@ -6800,7 +6800,7 @@ gtk_tree_view_put (GtkTreeView *tree_view,
 
   if (GTK_WIDGET_REALIZED (tree_view))
     gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
-
+  
   gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
 }
 
@@ -12355,7 +12355,9 @@ gtk_tree_view_remove_widget (GtkCellEditable *cell_editable,
     gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
   gtk_container_remove (GTK_CONTAINER (tree_view),
-                       GTK_WIDGET (cell_editable));
+                       GTK_WIDGET (cell_editable));  
+  /* FIXME should only redraw a single node */
+  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
 
 static gboolean